from typing import Union, Any


class Rows:
    data: list[list] = []
    keywords: list[str] = []

    def __init__(self, data: list[list], keywords: list[str]) -> None:
        self.data = data
        self.keywords = keywords

    def isRowTitle(self, row: list) -> bool:
        # if len(self.keywords) == 0:  # 如果没有keywords则默认第一行为title行
        #     return True
        # 每个keyword 都能在row中被找到则为true
        for keyword in self.keywords:
            for col in row:
                if isinstance(col, str) and keyword in col:
                    break
            else:
                # 如果所有col都没找到这个keyword
                return False
            if keyword == self.keywords[-1]:
                # 如果到了最后一个keyword
                return True  # 所有keyword都可以被找到
        else:
            return False  # 最后一个keyword未能被找到

    @property
    def titleIndex(self) -> Union[int, None]:
        """根据keywords找到title在第几个index

        Returns:
            Union[int, None]: 找到的title的index
        """
        for index, row in enumerate(self.data):
            if self.isRowTitle(row=row):
                return index
        else:
            return None

    @property
    def titleRow(self) -> list:
        """Title所在行对应的Row数据
        """
        titleIndex = self.titleIndex
        if isinstance(titleIndex, int):
            return self.data[titleIndex]
        else:
            return []

    def allTitleIndexesOf(self, name: str, titleRow: Union[list, None] = None) -> list[int]:
        """找到title所在行，名为name的所有index

        Args:
            name (str): 要找的title名称
            titleRow (Union[list, None], optional): 传入title行，为了节省运算时间. Defaults to None.

        Returns:
            list[int]: 对应title的所有index
        """
        row = titleRow if titleRow else self.titleRow
        result: list[int] = []
        for index, title in enumerate(row):
            if title == name:
                result.append(index)
        return result

    def validData(self, includingTitle: bool = True) -> list[list]:
        """有效数据从title行往后算

        Args:
            includingTitle (bool, optional): 是否包含title这列. Defaults to True.

        Returns:
            list[list]: 返回有效数据，从title行往后算
        """
        titleIndex = self.titleIndex
        if titleIndex is None:
            return []
        else:
            if includingTitle:
                return self.data[titleIndex:]
            elif titleIndex + 1 < len(self.data):
                return self.data[titleIndex+1:]
            else:
                return []

    def safeData(self, includingTitle: bool = True, fillWith: Union[Any, None] = None, desired: Union[int, list, None] = None) -> list[list]:
        """根据Title长度获得safe的list[list]，
        每个row的长度都至少是title这行的长度或指定的desired长度

        Args:
            includingTitle (bool, optional): 是否包含标题行. Defaults to True.
            fillWith (Union[Any, None], optional): 将空缺部分填充的内容. Defaults to None.
            desired (Union[int, list, None], optional): 每个row的目标length. Defaults to None.

        Returns:
            list[list]: _description_
        """
        titleRow = self.titleRow
        desiredLength: int = 0
        if isinstance(desired, int):
            desiredLength = desired
        elif isinstance(desired, list):
            desiredLength = len(desired)
        else:
            desiredLength = len(titleRow)
        result: list[list] = []
        for row in self.validData(includingTitle=includingTitle):
            toAppend = row + [fillWith for _ in range(len(row), desiredLength)]
            result.append(toAppend)
        return result

    def pickOut(self, colNames: list[str], includingTitle: bool = True, fillWith: Union[Any, None] = None) -> list[list]:
        """挑选出需要的列

        Args:
            colNames (list[str]): 需要的列的名称
            includingTitle (bool, optional): 是否包含标题. Defaults to True.
            fillWith (Union[Any, None], optional): 如果该列该行没有数据，则填充为. Defaults to None.

        Returns:
            list[list]: 挑选出列之后的数据
        """
        titleRow = self.titleRow
        safeData = self.safeData(
            includingTitle=includingTitle, fillWith=fillWith, desired=titleRow)
        allIndexes: list[int] = []
        for colName in colNames:
            allIndexes += self.allTitleIndexesOf(
                name=colName, titleRow=titleRow)
        allIndexes = list(set(allIndexes))
        allIndexes.sort()
        result: list[list] = []
        for row in safeData:
            toAppend = []
            for index in allIndexes:
                toAppend.append(row[index])
            result.append(toAppend)
        return result

    def toDictList(self, default: Union[str, int, float, None] = "") -> list[dict]:
        """将数据转为由dict组成的list

        Args:
            default (any, optional): 默认值，在遇到None或者数据不整齐时转为该值. Defaults to "".

        Returns:
            list[dict]: 根据已知数据转出的dict或者list
        """
        validData = self.validData(includingTitle=True)
        titles = validData[0]

        def rowToDict(row: list) -> dict:
            _rowRes = {}
            for index, colName in enumerate(titles):
                if index < len(row):
                    value = row[index]
                    _rowRes[colName] = default if value is None else value
                else:
                    _rowRes[colName] = default
            return _rowRes

        if len(validData) > 1:
            return [rowToDict(row) for row in validData[1:]]
        else:
            return []
